International aid may take the form of multilateral aid – provided through international bodies such as the UN, or NGOs such as Oxfam – or bilateral aid, which operates on a government-to-government basis. There is considerable debate about whether international aid works, in the sense of reducing poverty and stimulating development.

However, the effectiveness of aid is often diluted by corruption. Aid is invariably channeled through the governments of recipient countries, in which power is often concentrated in the hands of a few politicians and bureaucrats, and the mechanisms of accountability are, at best, poorly developed. This tends to benefit corrupt leaders and elites rather than the people, projects and programs for which it was intended.

The hypothesis that foreign aid can promote growth in developing countries was explored, using panel data series for foreign aid, while accounting for regional differences in Asian, African, Latin American, and the Caribbean countries as well as the differences in income levels, the results of this study also indicate that foreign aid has mixed effects on economic growth in developing countries.

This study examines the relationships between foreign aid, institutional structure, and economic performance for 80 countries in Europe, America, Africa, and Asia. It is found that official development assistance and the quality of institutional structure in the sample countries affect economic growth positively.

Loading libraries

Some libraries and packages used for data manipulation and data scrapping

library(tidyverse) # i don't think I´ll use this /r
── Attaching core tidyverse packages ───────────────────────────────────────────────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   3.5.1     ✔ tibble    3.2.1
✔ lubridate 1.9.3     ✔ tidyr     1.3.1
✔ purrr     1.0.2     ── Conflicts ─────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errors
library(WDI)       # for World Bank data acceding (mostly country code names)
library(readxl)    # for excel files reading
library(readr)     # for csv files reading
library(visdat)    # for data visualization
library(plotly)    # for plots

Adjuntando el paquete: ‘plotly’

The following object is masked from ‘package:ggplot2’:

    last_plot

The following object is masked from ‘package:stats’:

    filter

The following object is masked from ‘package:graphics’:

    layout
library(purrr)

Gathering Data

Data for low income countries will be used, as categorized by the World Bank there are 26 Low income countries and 51 Lower middle income countries

country_class <- read_excel("CLASS.xlsx")

country_class %>%
  filter(!is.na(Region), !is.na(`Income group`)) %>%
  group_by(`Income group`) %>%
  summarise(countries = n())

Here are listed countries to use:

my_countries <- country_class %>%
  filter(!is.na(Region), `Income group` %in% c('Low income', 'Lower middle income')) %>%
  select(Code)

Here we get the respective iso2c names

my_countries$iso2c <- WDI_data$country %>%
  filter(iso3c %in% my_countries$Code) %>%
  .$iso2c

Data from the World Bank API and the Human Development Reports API is dowloaded by the usage of Python Scripts. They are stored as csv files and then loaded here:

HDI

datos_HDI <- read_csv("datos_python_HDI.csv", col_names = c('Code', 'iso2c', 'indicator', 'year', 'value'), 
                      col_types = list(col_character(), col_character(), col_character(), col_double(), col_double()))

hdi_indicators <- datos_HDI %>% distinct(indicator) %>% .$indicator

ODA

oda_indicators <- c(
'DT_ODA_ALLD_CD',
'DT_ODA_ALLD_KD',
'DT_ODA_OATL_CD',
'DT_ODA_OATL_KD',
'DT_ODA_ODAT_CD',
'DT_ODA_ODAT_GI_ZS',
'DT_ODA_ODAT_GN_ZS',
'DT_ODA_ODAT_KD',
'DT_ODA_ODAT_MP_ZS',
'DT_ODA_ODAT_PC_ZS',
'DT_ODA_ODAT_XP_ZS'
)
gob_indicators <- c(
'CC_EST',
'CC_NO_SRC',
'CC_PER_RNK',
'CC_PER_RNK_LOWER',
'CC_PER_RNK_UPPER',
'CC_STD_ERR',
'GE_EST',
'GE_NO_SRC',
'GE_PER_RNK',
'GE_PER_RNK_LOWER',
'GE_PER_RNK_UPPER',
'GE_STD_ERR',
'PV_EST',
'PV_NO_SRC',
'PV_PER_RNK',
'PV_PER_RNK_LOWER',
'PV_PER_RNK_UPPER',
'PV_STD_ERR',
'RQ_EST',
'RQ_NO_SRC',
'RQ_PER_RNK',
'RQ_PER_RNK_LOWER',
'RQ_PER_RNK_UPPER',
'RQ_STD_ERR',
'RL_EST')

datos_WB <- data.frame(indicator = character(), iso2c = character(), year = double(), value = double())

suppressWarnings(
  for (indicator in c(oda_indicators, gob_indicators)) {
    datos_WB <- rbind(datos_WB, read_csv(paste("datos_python", indicator, ".csv", sep =''), 
                                           col_names = c('indicator', 'iso2c', 'year', 'value'),
                                           col_types = list(col_character(), col_character(), col_double(), col_double())))
  }
)

Data Manipulation

Transform the data into a new structure for easier understanding

datos_paper <- rbind(datos_WB, datos_HDI %>% select(indicator, iso2c, year, value)) %>%
  pivot_wider(names_from = indicator, values_from = value)

Lets check which data is missing…

vis_dat(datos_paper %>% select(all_of(gsub("_", ".", oda_indicators)))) 

  # DT.ODA.OATL.CD and DT.ODA.OATL.KD missing for all countries and years
  # DT.ODA.ODAT.GI.ZS, DT.ODA.ODAT.GN.ZS, DT.ODA.ODAT.MP.ZS and DT.ODA.ODAT.XP.ZS also has some missing values
  # There is a couple of countries that has some missing values for some exact years

Taking into account the missing data let´s select a smaller sample to test

Now lets view data again with those filters

From 1925 to 1098 rows huh… i don’t know…

Let’s give it a shot with a linear model

summary(model)

Call:
lm(formula = hdi ~ DT.ODA.ALLD.CD + CC.EST + GE.EST + PV.EST + 
    RQ.EST + RL.EST, data = datos_model)

Residuals:
      Min        1Q    Median        3Q       Max 
-0.291363 -0.060809  0.001437  0.062167  0.195139 

Coefficients:
                 Estimate Std. Error t value Pr(>|t|)    
(Intercept)     5.881e-01  5.818e-03 101.081  < 2e-16 ***
DT.ODA.ALLD.CD  2.008e-12  2.589e-12   0.776  0.43815    
CC.EST         -6.896e-02  1.085e-02  -6.355 3.05e-10 ***
GE.EST          1.533e-01  1.107e-02  13.849  < 2e-16 ***
PV.EST          9.200e-03  4.513e-03   2.039  0.04172 *  
RQ.EST         -3.501e-02  1.065e-02  -3.288  0.00104 ** 
RL.EST          2.094e-02  1.204e-02   1.738  0.08243 .  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.08902 on 1091 degrees of freedom
Multiple R-squared:  0.2893,    Adjusted R-squared:  0.2854 
F-statistic:    74 on 6 and 1091 DF,  p-value: < 2.2e-16

It worked!!! but I just threw random variables in there, I want to see their relationship with HID

#Data visualization

… what was that??? I guess I cant just throw things in there and expect to have a good model, I can’t see a clear relationship between this stuff, more than better governance indicators are usually accompanied with better HDI scores. But… I was saying that I wanted to find a relationship with HDI changes, not the actual HDI score. So, I’ll compute a HDI change per year per country, (and lose 61 rows in the process, yay…)

Data manipulation 2 Electric boogaloo

Note: originally I was excluding data from 2001, because some countries didn’t have governance indicators for that year particularly, but!, since I’ll lose one year by computing the growth in hdi I can still use this year and wont loose data al all. STONKS!!!

and here we go again

Testing model while using hdi_diff as dependent variable (it went better than expected)

summary(model_3)

Call:
lm(formula = hdi_diff ~ DT.ODA.ALLD.CD + CC.EST + GE.EST + PV.EST + 
    RQ.EST + RL.EST, data = datos_model_3)

Residuals:
      Min        1Q    Median        3Q       Max 
-0.084650 -0.002575  0.000074  0.002727  0.074605 

Coefficients:
                 Estimate Std. Error t value Pr(>|t|)    
(Intercept)     6.437e-03  4.444e-04  14.485  < 2e-16 ***
DT.ODA.ALLD.CD -6.826e-14  1.978e-13  -0.345  0.73005    
CC.EST          6.344e-04  8.289e-04   0.765  0.44421    
GE.EST          2.211e-03  8.457e-04   2.615  0.00905 ** 
PV.EST          1.058e-03  3.448e-04   3.070  0.00219 ** 
RQ.EST         -1.227e-03  8.134e-04  -1.509  0.13169    
RL.EST         -2.355e-03  9.200e-04  -2.560  0.01060 *  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.006801 on 1091 degrees of freedom
Multiple R-squared:  0.01844,   Adjusted R-squared:  0.01304 
F-statistic: 3.416 on 6 and 1091 DF,  p-value: 0.002404

I liked the relationship visible in the PER.RNK gov indicators, let’s try a model with those variables (it went worse than expected)

summary(model_4)

Call:
lm(formula = hdi_diff ~ DT.ODA.ALLD.CD + CC.PER.RNK + GE.PER.RNK + 
    PV.PER.RNK + RQ.PER.RNK + RL.EST, data = datos_model_3)

Residuals:
      Min        1Q    Median        3Q       Max 
-0.085300 -0.002458  0.000048  0.002847  0.074421 

Coefficients:
                 Estimate Std. Error t value Pr(>|t|)   
(Intercept)     4.239e-03  1.620e-03   2.616  0.00902 **
DT.ODA.ALLD.CD -2.927e-13  1.917e-13  -1.527  0.12711   
CC.PER.RNK      2.002e-05  2.154e-05   0.930  0.35272   
GE.PER.RNK      4.254e-05  2.599e-05   1.637  0.10192   
PV.PER.RNK      9.925e-06  1.451e-05   0.684  0.49422   
RQ.PER.RNK     -3.012e-05  2.547e-05  -1.182  0.23733   
RL.EST         -1.296e-03  9.288e-04  -1.395  0.16323   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.006842 on 1091 degrees of freedom
Multiple R-squared:  0.006585,  Adjusted R-squared:  0.001122 
F-statistic: 1.205 on 6 and 1091 DF,  p-value: 0.3009
LS0tDQp0aXRsZTogIk9mZmljaWFsIERldmVsb3BtZW50IEFzc2lzdGFuY2UgYW5kIEluc3RpdHV0aW9uYWwgUXVhbGl0eSBvbiBVbmRldmVsb3BlZCBjb3VudHJpZXMiDQpvdXRwdXQ6DQogIHBkZl9kb2N1bWVudDogZGVmYXVsdA0KICBodG1sX25vdGVib29rOiBkZWZhdWx0DQpkYXRlOiAiMjAyNC0wOC0wNSINCmF1dGhvcjogIk9zY2FyIEVkdWFyZG8gTW9yYWxlcyBDw6FyZGVuYXMiDQotLS0NCg0KDQpJbnRlcm5hdGlvbmFsIGFpZCBtYXkgdGFrZSB0aGUgZm9ybSBvZiBtdWx0aWxhdGVyYWwgYWlkIOKAkyBwcm92aWRlZCB0aHJvdWdoIGludGVybmF0aW9uYWwgYm9kaWVzIHN1Y2ggYXMgdGhlIFVOLCBvciBOR09zIHN1Y2ggYXMgT3hmYW0g4oCTIG9yIGJpbGF0ZXJhbCBhaWQsIHdoaWNoIG9wZXJhdGVzIG9uIGEgZ292ZXJubWVudC10by1nb3Zlcm5tZW50IGJhc2lzLiBUaGVyZSBpcyBjb25zaWRlcmFibGUgZGViYXRlIGFib3V0IHdoZXRoZXIgaW50ZXJuYXRpb25hbCBhaWQgd29ya3MsIGluIHRoZSBzZW5zZSBvZiByZWR1Y2luZyBwb3ZlcnR5IGFuZCBzdGltdWxhdGluZyBkZXZlbG9wbWVudC4NCg0KSG93ZXZlciwgdGhlIGVmZmVjdGl2ZW5lc3Mgb2YgYWlkIGlzIG9mdGVuIGRpbHV0ZWQgYnkgY29ycnVwdGlvbi4gQWlkIGlzIGludmFyaWFibHkgY2hhbm5lbGVkIHRocm91Z2ggdGhlIGdvdmVybm1lbnRzIG9mIHJlY2lwaWVudCBjb3VudHJpZXMsIGluIHdoaWNoIHBvd2VyIGlzIG9mdGVuIGNvbmNlbnRyYXRlZCBpbiB0aGUgaGFuZHMgb2YgYSBmZXcgcG9saXRpY2lhbnMgYW5kIGJ1cmVhdWNyYXRzLCBhbmQgdGhlIG1lY2hhbmlzbXMgb2YgYWNjb3VudGFiaWxpdHkgYXJlLCBhdCBiZXN0LCBwb29ybHkgZGV2ZWxvcGVkLiBUaGlzIHRlbmRzIHRvIGJlbmVmaXQgY29ycnVwdCBsZWFkZXJzIGFuZCBlbGl0ZXMgcmF0aGVyIHRoYW4gdGhlIHBlb3BsZSwgcHJvamVjdHMgYW5kIHByb2dyYW1zIGZvciB3aGljaCBpdCB3YXMgaW50ZW5kZWQuDQoNClxiZWdpbntmbHVzaHJpZ2h0fQ0KV2F0dHMsIENhcmwuICgyMDE0KS4gUmU6IERvZXMgZm9yZWlnbiBhaWQgaGVscCB0aGUgZGV2ZWxvcGluZyBjb3VudHJpZXMgdG93YXJkcyBkZXZlbG9wbWVudD8uIFJldHJpZXZlZCBmcm9tOiAkaHR0cHM6Ly93d3cucmVzZWFyY2hnYXRlLm5ldC9wb3N0L0RvZXNfZm9yZWlnbl9haWRfaGVscF90aGVfZGV2ZWxvcGluZ19jb3VudHJpZXNfdG93YXJkc19kZXZlbG9wbWVudC81MzIyMDA1ZWQwMzliMWU3NjQ4YjQ1OWMvY2l0YXRpb24vZG93bmxvYWQuJA0KXGVuZHtmbHVzaHJpZ2h0fQ0KDQoNClRoZSBoeXBvdGhlc2lzIHRoYXQgZm9yZWlnbiBhaWQgY2FuIHByb21vdGUgZ3Jvd3RoIGluIGRldmVsb3BpbmcgY291bnRyaWVzIHdhcyBleHBsb3JlZCwgdXNpbmcgcGFuZWwgZGF0YSBzZXJpZXMgZm9yIGZvcmVpZ24gYWlkLCB3aGlsZSBhY2NvdW50aW5nIGZvciByZWdpb25hbCBkaWZmZXJlbmNlcyBpbiBBc2lhbiwgQWZyaWNhbiwgTGF0aW4gQW1lcmljYW4sIGFuZCB0aGUgQ2FyaWJiZWFuIGNvdW50cmllcyBhcyB3ZWxsIGFzIHRoZSBkaWZmZXJlbmNlcyBpbiBpbmNvbWUgbGV2ZWxzLCB0aGUgcmVzdWx0cyBvZiB0aGlzIHN0dWR5IGFsc28gaW5kaWNhdGUgdGhhdCBmb3JlaWduIGFpZCBoYXMgbWl4ZWQgZWZmZWN0cyBvbiBlY29ub21pYyBncm93dGggaW4gZGV2ZWxvcGluZyBjb3VudHJpZXMuDQoNClxiZWdpbntmbHVzaHJpZ2h0fQ0KRWthbmF5YWtlLCBFLiAmIENoYXRybmEsIERhc2hhLiAoMjAxMCkuIFRoZSBlZmZlY3Qgb2YgZm9yZWlnbiBhaWQgb24gZWNvbm9taWMgZ3Jvd3RoIGluIGRldmVsb3BpbmcgY291bnRyaWVzLiBKb3VybmFsIG9mIEludGVybmF0aW9uYWwgQnVzaW5lc3MgYW5kIEN1bHR1cmFsIFN0dWRpZXMuIDMuDQpcZW5ke2ZsdXNocmlnaHR9DQoNCg0KVGhpcyBzdHVkeSBleGFtaW5lcyB0aGUgcmVsYXRpb25zaGlwcyBiZXR3ZWVuIGZvcmVpZ24gYWlkLCBpbnN0aXR1dGlvbmFsIHN0cnVjdHVyZSwgYW5kIGVjb25vbWljIHBlcmZvcm1hbmNlIGZvciA4MCBjb3VudHJpZXMgaW4gRXVyb3BlLCBBbWVyaWNhLCBBZnJpY2EsIGFuZCBBc2lhLiBJdCBpcyBmb3VuZCB0aGF0IG9mZmljaWFsIGRldmVsb3BtZW50IGFzc2lzdGFuY2UgYW5kIHRoZSBxdWFsaXR5IG9mIGluc3RpdHV0aW9uYWwgc3RydWN0dXJlIGluIHRoZSBzYW1wbGUgY291bnRyaWVzIGFmZmVjdCBlY29ub21pYyBncm93dGggcG9zaXRpdmVseS4NCg0KXGJlZ2lue2ZsdXNocmlnaHR9DQpIYXlhbG/En2x1LCBQxLFuYXIuICgyMDIzKS4gRm9yZWlnbiBBaWQsIEluc3RpdHV0aW9ucywgYW5kIEVjb25vbWljIFBlcmZvcm1hbmNlIGluIERldmVsb3BpbmcgQ291bnRyaWVzLiBFc2tpxZ9laGlyIE9zbWFuZ2F6aSDDnG5pdmVyc2l0ZXNpIMSwa3Rpc2FkaSB2ZSDEsGRhcmkgQmlsaW1sZXIgRGVyZ2lzaS4gMTguIDc0OC03NjUuIDEwLjE3MTUzL29ndWlpYmYuMTI3NzM0OC4gDQpcZW5ke2ZsdXNocmlnaHR9DQoNCiMgTG9hZGluZyBsaWJyYXJpZXMNCg0KU29tZSBsaWJyYXJpZXMgYW5kIHBhY2thZ2VzIHVzZWQgZm9yIGRhdGEgbWFuaXB1bGF0aW9uIGFuZCBkYXRhIHNjcmFwcGluZw0KDQpgYGB7cn0NCmxpYnJhcnkodGlkeXZlcnNlKSAjIGkgZG9uJ3QgdGhpbmsgScK0bGwgdXNlIHRoaXMgL3INCmxpYnJhcnkoV0RJKSAgICAgICAjIGZvciBXb3JsZCBCYW5rIGRhdGEgYWNjZWRpbmcgKG1vc3RseSBjb3VudHJ5IGNvZGUgbmFtZXMpDQpsaWJyYXJ5KHJlYWR4bCkgICAgIyBmb3IgZXhjZWwgZmlsZXMgcmVhZGluZw0KbGlicmFyeShyZWFkcikgICAgICMgZm9yIGNzdiBmaWxlcyByZWFkaW5nDQpsaWJyYXJ5KHZpc2RhdCkgICAgIyBmb3IgZGF0YSB2aXN1YWxpemF0aW9uDQpsaWJyYXJ5KHBsb3RseSkgICAgIyBmb3IgcGxvdHMNCmxpYnJhcnkocHVycnIpICAgICAjIGZvciBtYXAgZnVuY2l0b24NCmBgYA0KDQojIEdhdGhlcmluZyBEYXRhDQoNCkRhdGEgZm9yIGxvdyBpbmNvbWUgY291bnRyaWVzIHdpbGwgYmUgdXNlZCwgYXMgY2F0ZWdvcml6ZWQgYnkgdGhlIFdvcmxkIEJhbmsgdGhlcmUgYXJlIDI2IExvdyBpbmNvbWUgY291bnRyaWVzIGFuZCA1MSBMb3dlciBtaWRkbGUgaW5jb21lIGNvdW50cmllcw0KDQpgYGB7cn0NCmNvdW50cnlfY2xhc3MgPC0gcmVhZF9leGNlbCgiQ0xBU1MueGxzeCIpDQoNCmNvdW50cnlfY2xhc3MgJT4lDQogIGZpbHRlcighaXMubmEoUmVnaW9uKSwgIWlzLm5hKGBJbmNvbWUgZ3JvdXBgKSkgJT4lDQogIGdyb3VwX2J5KGBJbmNvbWUgZ3JvdXBgKSAlPiUNCiAgc3VtbWFyaXNlKGNvdW50cmllcyA9IG4oKSkNCmBgYA0KDQpIZXJlIGFyZSBsaXN0ZWQgY291bnRyaWVzIHRvIHVzZToNCg0KYGBge3J9DQpteV9jb3VudHJpZXMgPC0gY291bnRyeV9jbGFzcyAlPiUNCiAgZmlsdGVyKCFpcy5uYShSZWdpb24pLCBgSW5jb21lIGdyb3VwYCAlaW4lIGMoJ0xvdyBpbmNvbWUnLCAnTG93ZXIgbWlkZGxlIGluY29tZScpKSAlPiUNCiAgc2VsZWN0KENvZGUpDQpgYGANCg0KSGVyZSB3ZSBnZXQgdGhlIHJlc3BlY3RpdmUgaXNvMmMgbmFtZXMNCg0KYGBge3J9DQpteV9jb3VudHJpZXMkaXNvMmMgPC0gV0RJX2RhdGEkY291bnRyeSAlPiUNCiAgZmlsdGVyKGlzbzNjICVpbiUgbXlfY291bnRyaWVzJENvZGUpICU+JQ0KICAuJGlzbzJjDQpgYGANCg0KRGF0YSBmcm9tIHRoZSBXb3JsZCBCYW5rIEFQSSBhbmQgdGhlIEh1bWFuIERldmVsb3BtZW50IFJlcG9ydHMgQVBJIGlzIGRvd2xvYWRlZCBieSB0aGUgdXNhZ2Ugb2YgUHl0aG9uIFNjcmlwdHMuDQpUaGV5IGFyZSBzdG9yZWQgYXMgY3N2IGZpbGVzIGFuZCB0aGVuIGxvYWRlZCBoZXJlOg0KDQojIyBIREkNCg0KYGBge3J9DQpkYXRvc19IREkgPC0gcmVhZF9jc3YoImRhdG9zX3B5dGhvbl9IREkuY3N2IiwgY29sX25hbWVzID0gYygnQ29kZScsICdpc28yYycsICdpbmRpY2F0b3InLCAneWVhcicsICd2YWx1ZScpLCANCiAgICAgICAgICAgICAgICAgICAgICBjb2xfdHlwZXMgPSBsaXN0KGNvbF9jaGFyYWN0ZXIoKSwgY29sX2NoYXJhY3RlcigpLCBjb2xfY2hhcmFjdGVyKCksIGNvbF9kb3VibGUoKSwgY29sX2RvdWJsZSgpKSkNCg0KaGRpX2luZGljYXRvcnMgPC0gZGF0b3NfSERJICU+JSBkaXN0aW5jdChpbmRpY2F0b3IpICU+JSAuJGluZGljYXRvcg0KYGBgDQoNCiMjIE9EQQ0KDQpgYGB7cn0NCm9kYV9pbmRpY2F0b3JzIDwtIGMoDQonRFRfT0RBX0FMTERfQ0QnLA0KJ0RUX09EQV9BTExEX0tEJywNCidEVF9PREFfT0FUTF9DRCcsDQonRFRfT0RBX09BVExfS0QnLA0KJ0RUX09EQV9PREFUX0NEJywNCidEVF9PREFfT0RBVF9HSV9aUycsDQonRFRfT0RBX09EQVRfR05fWlMnLA0KJ0RUX09EQV9PREFUX0tEJywNCidEVF9PREFfT0RBVF9NUF9aUycsDQonRFRfT0RBX09EQVRfUENfWlMnLA0KJ0RUX09EQV9PREFUX1hQX1pTJw0KKQ0KZ29iX2luZGljYXRvcnMgPC0gYygNCidDQ19FU1QnLA0KJ0NDX05PX1NSQycsDQonQ0NfUEVSX1JOSycsDQonQ0NfUEVSX1JOS19MT1dFUicsDQonQ0NfUEVSX1JOS19VUFBFUicsDQonQ0NfU1REX0VSUicsDQonR0VfRVNUJywNCidHRV9OT19TUkMnLA0KJ0dFX1BFUl9STksnLA0KJ0dFX1BFUl9STktfTE9XRVInLA0KJ0dFX1BFUl9STktfVVBQRVInLA0KJ0dFX1NURF9FUlInLA0KJ1BWX0VTVCcsDQonUFZfTk9fU1JDJywNCidQVl9QRVJfUk5LJywNCidQVl9QRVJfUk5LX0xPV0VSJywNCidQVl9QRVJfUk5LX1VQUEVSJywNCidQVl9TVERfRVJSJywNCidSUV9FU1QnLA0KJ1JRX05PX1NSQycsDQonUlFfUEVSX1JOSycsDQonUlFfUEVSX1JOS19MT1dFUicsDQonUlFfUEVSX1JOS19VUFBFUicsDQonUlFfU1REX0VSUicsDQonUkxfRVNUJykNCg0KZGF0b3NfV0IgPC0gZGF0YS5mcmFtZShpbmRpY2F0b3IgPSBjaGFyYWN0ZXIoKSwgaXNvMmMgPSBjaGFyYWN0ZXIoKSwgeWVhciA9IGRvdWJsZSgpLCB2YWx1ZSA9IGRvdWJsZSgpKQ0KDQpzdXBwcmVzc1dhcm5pbmdzKA0KICBmb3IgKGluZGljYXRvciBpbiBjKG9kYV9pbmRpY2F0b3JzLCBnb2JfaW5kaWNhdG9ycykpIHsNCiAgICBkYXRvc19XQiA8LSByYmluZChkYXRvc19XQiwgcmVhZF9jc3YocGFzdGUoImRhdG9zX3B5dGhvbiIsIGluZGljYXRvciwgIi5jc3YiLCBzZXAgPScnKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sX25hbWVzID0gYygnaW5kaWNhdG9yJywgJ2lzbzJjJywgJ3llYXInLCAndmFsdWUnKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xfdHlwZXMgPSBsaXN0KGNvbF9jaGFyYWN0ZXIoKSwgY29sX2NoYXJhY3RlcigpLCBjb2xfZG91YmxlKCksIGNvbF9kb3VibGUoKSkpKQ0KICB9DQopDQpgYGANCg0KIyBEYXRhIE1hbmlwdWxhdGlvbg0KDQpUcmFuc2Zvcm0gdGhlIGRhdGEgaW50byBhIG5ldyBzdHJ1Y3R1cmUgZm9yIGVhc2llciB1bmRlcnN0YW5kaW5nDQoNCmBgYHtyfQ0KZGF0b3NfcGFwZXIgPC0gcmJpbmQoZGF0b3NfV0IsIGRhdG9zX0hESSAlPiUgc2VsZWN0KGluZGljYXRvciwgaXNvMmMsIHllYXIsIHZhbHVlKSkgJT4lDQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBpbmRpY2F0b3IsIHZhbHVlc19mcm9tID0gdmFsdWUpDQpgYGANCg0KTGV0cyBjaGVjayB3aGljaCBkYXRhIGlzIG1pc3NpbmcuLi4NCg0KYGBge3J9DQp2aXNfZGF0KGRhdG9zX3BhcGVyICU+JSBzZWxlY3QoYWxsX29mKGdzdWIoIl8iLCAiLiIsIG9kYV9pbmRpY2F0b3JzKSkpKSANCiAgIyBEVC5PREEuT0FUTC5DRCBhbmQgRFQuT0RBLk9BVEwuS0QgbWlzc2luZyBmb3IgYWxsIGNvdW50cmllcyBhbmQgeWVhcnMNCiAgIyBEVC5PREEuT0RBVC5HSS5aUywgRFQuT0RBLk9EQVQuR04uWlMsIERULk9EQS5PREFULk1QLlpTIGFuZCBEVC5PREEuT0RBVC5YUC5aUyBhbHNvIGhhcyBzb21lIG1pc3NpbmcgdmFsdWVzDQogICMgVGhlcmUgaXMgYSBjb3VwbGUgb2YgY291bnRyaWVzIHRoYXQgaGFzIHNvbWUgbWlzc2luZyB2YWx1ZXMgZm9yIHNvbWUgZXhhY3QgeWVhcnMNCmBgYA0KYGBge3J9DQp2aXNfZGF0KGRhdG9zX3BhcGVyICU+JSBhcnJhbmdlKHllYXIpICU+JQ0KICAgICAgICAgIHNlbGVjdChhbGxfb2YoZ3N1YigiXyIsICIuIiwgZ29iX2luZGljYXRvcnMpKSkpIA0KICAjIEl0IHNlZW1zIHRoYXQgc29tZSB5ZWFycyBhcmUgbWlzc2luZyBoZXJlLCBzaG91bGQgd2UgdGFrZSBmcm9tIChhbG1vc3QpIHRoZSBoYWxmIGFuZCB1cHdhcmQ/IA0KYGBgDQpgYGB7cn0NCnZpc19kYXQoZGF0b3NfcGFwZXIgJT4lDQogICAgICAgICAgc2VsZWN0KGFsbF9vZihoZGlfaW5kaWNhdG9ycykpKSANCiAgIyBhYnIsIGNvMl9wcm9kLCBsZSwgbGVfZiwgbGVfbSwgbW1yIHNlZW1zIGxpa2UgaGFzIGFsbCB0aGUgeWVhcnMsIGJ1dC4uLiBkb2Vzbid0IGhkaT8gDQpgYGANCg0KYGBge3J9DQp2aXNfZGF0KGRhdG9zX3BhcGVyICU+JSBhcnJhbmdlKHllYXIpICU+JSBzZWxlY3QoaGRpKSkgDQogICMgaGRpIG1pc3NpbmcgaW4gdmFyaW91cyBjb3VudHJpZXMgYW5kIHllYXJzLi4uIHdoYXQgZG8gd2UgZG8/DQpgYGANClRha2luZyBpbnRvIGFjY291bnQgdGhlIG1pc3NpbmcgZGF0YSBsZXTCtHMgc2VsZWN0IGEgc21hbGxlciBzYW1wbGUgdG8gdGVzdA0KYGBge3J9DQpkYXRvc19wYXBlciAlPiUgZmlsdGVyKGlzLm5hKERULk9EQS5BTExELkNEKSkgIyMgQ3VscHJpdCBpcyBTUyAoU291dGggU3VkYW4pIGFuZCBaVyAoWmltYmFid2UpIHRoZXkgaGF2ZSBhbG1vc3Qgbm8gT0RBIGFuZA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMjIEdPQiBpbmRpY2F0b3JzDQpkYXRvc19wYXBlciAlPiUgZmlsdGVyKCFpc28yYyAlaW4lIGMoJ1NTJywgJ1pXJykpICU+JSBmaWx0ZXIoaXMubmEoQ0MuRVNUKSkgJT4lIGdyb3VwX2J5KHllYXIpICU+JSBzdW1tYXJpc2UodGltZXMgPSBuKCkpDQogICMgaXQgc2VlbXMgdGhhdCAxOTk1LCAxOTk3LCAxOTk5IGFuZCAyMDAxIGRpZG4ndCBtZWFzdXJlIGdvdmVybmFuY2UgaW5kaWNhdG9ycyBhdCBhbGwNCiAgIyAxOTk2LCAxOTk4LCAyMDAwLCAyMDAyIGFuZCAyMDAzIGhhcyBzb21lIG1pc3NpbmcgY291bnRyaWVzLCBpdCBzZWVtcyBsZXRzIHRha2UgYSBsb29rDQpkYXRvc19wYXBlciAlPiUgYXJyYW5nZSh5ZWFyKSAlPiUgZmlsdGVyKCFpc28yYyAlaW4lIGMoJ1NTJywgJ1pXJyksICF5ZWFyICVpbiUgYygxOTk1LCAxOTk3LCAxOTk5LCAyMDAxKSkgJT4lDQogICAgICAgICAgICAgICAgZmlsdGVyKGlzLm5hKENDLkVTVCkpICMgRk0gKE1pY3JvbmVzaWEpLCBLSSAoS2lyaWJhdGkpIGFuZCBUTCAoVGltb3ItTGVzdGUpIGRpZG50IGhhdmUgR09CIGluIHRob3NlIHllYXJzDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgYWxzbyBDViAoQ2FibyBWZXJkZSkgYW5kIFNCIChTb2xvbW9uIElzbGFuZHMpIGRpZG4ndCByZWdpc3RlciBzb21lIEdPQiBpbiAyMDAwIC0gMDMNCmBgYA0KTm93IGxldHMgdmlldyBkYXRhIGFnYWluIHdpdGggdGhvc2UgZmlsdGVycw0KYGBge3J9DQpkYXRvc19wYXBlciAlPiUgDQogICAgICAgICAgYXJyYW5nZShpc28yYykgJT4lIA0KICAgICAgICAgIGZpbHRlcighaXNvMmMgJWluJSBjKCdTUycsICdaVycsICdCVCcsICdFUicsICdHVycsICdLUCcsICdMQicsICdORycsICdQUycsICdTTycsICdWVScsICdGTScsICdLSScsICdUTCcpLCANCiAgICAgICAgICAgICAgICAgIXllYXIgJWluJSBjKDE5OTUsIDE5OTYsIDE5OTcsIDE5OTgsIDE5OTksIDIwMDEpKSAlPiUNCiAgICAgICAgICBzZWxlY3QoaXNvMmMsIHllYXIsIGhkaSwNCiAgICAgICAgICAgICAgICAgYWxsX29mKGdzdWIoIl8iLCAiLiIsIGdvYl9pbmRpY2F0b3JzKSkNCiAgICAgICAgICAgICAgICAgKSAlPiUNCiAgICAgICAgIGZpbHRlcihpcy5uYShHRS5FU1QpKSAjJT4lDQogICAgICAgICAjIGdyb3VwX2J5KHllYXIpICU+JQ0KICAgICAgICAgIyBzdW1tYXJpc2UodGltZXMgPSBuKCkpIA0KIyAxOTk2IGFuZCAxOTk4IGFyZSB0cm91Ymxlc29tZSwgc28gbGV0cyBzdGFydCBpbiAyMDAwDQojIEJUIChCaHV0YW4pLCBFUiAoRXJpdHJlYSksIEdXIChHdWluZWEtQmlzc2F1KSwgS1AgKE5vcnRoIEtvcmVhKSwgTEIgKExlYmFub24pLCBORyAoTmlnZXJpYSksIFBTIChQYWxlc3RpbmUpLCBTTyAoU29tYWxpYSksDQojIFZVIChWYW51YXR1KSBhcmUgdGhlIGNvdW50cmllcyB3aXRob3V0IGhkaQ0KYGBgDQoNCmBgYHtyfQ0KdmlzX2RhdChkYXRvc19wYXBlciAlPiUgDQogICAgICAgIGZpbHRlcighaXNvMmMgJWluJSBjKCdTUycsICdaVycsICdCVCcsICdFUicsICdHVycsICdLUCcsICdMQicsICdORycsICdQUycsICdTTycsICdWVScsICdGTScsICdLSScsICdUTCcsICdDVicsICdTQicpLA0KICAgICAgICAgICAgICAgIXllYXIgJWluJSBjKDE5OTUsIDE5OTYsIDE5OTcsIDE5OTgsIDE5OTksIDIwMDAsIDIwMDEpKSAlPiUNCiAgICAgICAgc2VsZWN0KGlzbzJjLCB5ZWFyLCBoZGksIERULk9EQS5BTExELkNELCBEVC5PREEuQUxMRC5LRCwgRFQuT0RBLk9EQVQuQ0QsIERULk9EQS5PREFULktELCBEVC5PREEuT0RBVC5QQy5aUywNCiAgICAgICAgICAgICAgIGFsbF9vZihnc3ViKCJfIiwgIi4iLCBnb2JfaW5kaWNhdG9ycykpDQogICAgICAgICAgICAgICApKQ0KYGBgDQpGcm9tIDE5MjUgdG8gMTA5OCByb3dzIGh1aC4uLiBpIGRvbid0IGtub3cuLi4NCmBgYHtyfQ0KZGF0b3NfbW9kZWwgPC0gZGF0b3NfcGFwZXIgJT4lIA0KICAgICAgICBmaWx0ZXIoIWlzbzJjICVpbiUgYygnU1MnLCAnWlcnLCAnQlQnLCAnRVInLCAnR1cnLCAnS1AnLCAnTEInLCAnTkcnLCAnUFMnLCAnU08nLCAnVlUnLCAnRk0nLCAnS0knLCAnVEwnLCAnQ1YnLCAnU0InKSwNCiAgICAgICAgICAgICAgICF5ZWFyICVpbiUgYygxOTk1LCAxOTk2LCAxOTk3LCAxOTk4LCAxOTk5LCAyMDAwLCAyMDAxKSkgJT4lDQogICAgICAgIHNlbGVjdChpc28yYywgeWVhciwgaGRpLCBEVC5PREEuQUxMRC5DRCwgRFQuT0RBLkFMTEQuS0QsIERULk9EQS5PREFULkNELCBEVC5PREEuT0RBVC5LRCwgRFQuT0RBLk9EQVQuUEMuWlMsDQogICAgICAgICAgICAgICBhbGxfb2YoZ3N1YigiXyIsICIuIiwgZ29iX2luZGljYXRvcnMpKQ0KICAgICAgICAgICAgICAgKQ0KYGBgDQoNCkxldCdzIGdpdmUgaXQgYSBzaG90IHdpdGggYSBsaW5lYXIgbW9kZWwNCmBgYHtyfQ0KbW9kZWwgPC0gbG0oaGRpIH4gRFQuT0RBLkFMTEQuQ0QgKyBDQy5FU1QgKyBHRS5FU1QgKyBQVi5FU1QgKyBSUS5FU1QgKyBSTC5FU1QsIGRhdGE9ZGF0b3NfbW9kZWwpDQpzdW1tYXJ5KG1vZGVsKQ0KYGBgDQpJdCB3b3JrZWQhISENCmJ1dCBJIGp1c3QgdGhyZXcgcmFuZG9tIHZhcmlhYmxlcyBpbiB0aGVyZSwgSSB3YW50IHRvIHNlZSB0aGVpciByZWxhdGlvbnNoaXAgd2l0aCBISUQNCg0KI0RhdGEgdmlzdWFsaXphdGlvbg0KDQpgYGB7cn0NCm15X3Bsb3QgIDwtIGxpc3QoKQ0KDQpmb3IgKGNvbCBpbiBjb2xuYW1lcyhkYXRvc19tb2RlbClbNDozM10pIHsNCiAgbXlfcGxvdFtbY29sXV0gPC0gcGxvdF9seSh4ID0gZGF0b3NfbW9kZWxbW2NvbF1dLCB5ID0gZGF0b3NfbW9kZWxbWzNdXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlID0gJ3NjYXR0ZXInLCBtb2RlID0gJ21hcmtlcnMnLCBuYW1lID0gcGFzdGUoY29sLCAidnMgSERJIikpICANCn0NCg0KDQpzdWJwbG90KG15X3Bsb3RbMTo1XSwgbnJvd3MgPSAyLCBtYXJnaW4gPSAwLjA1KSAlPiUgbGF5b3V0KHRpdGxlID0gJ09EQSB2cyBIREknKQ0KDQpgYGANCg0KYGBge3J9DQpzdWJwbG90KG15X3Bsb3RbNjoxMV0sIG5yb3dzID0gMiwgbWFyZ2luID0gMC4wNSkgJT4lIGxheW91dCh0aXRsZSA9ICdDQyB2cyBIREknKQ0KYGBgDQoNCmBgYHtyfQ0Kc3VicGxvdChteV9wbG90WzEyOjE3XSwgbnJvd3MgPSAyLCBtYXJnaW4gPSAwLjA1KSAlPiUgbGF5b3V0KHRpdGxlID0gJ0dFIHZzIEhESScpDQpgYGANCg0KDQpgYGB7cn0NCnN1YnBsb3QobXlfcGxvdFsxODoyM10sIG5yb3dzID0gMiwgbWFyZ2luID0gMC4wNSkgJT4lIGxheW91dCh0aXRsZSA9ICdQViB2cyBIREknKQ0KYGBgDQoNCmBgYHtyfQ0Kc3VicGxvdChteV9wbG90WzI0OjI5XSwgbnJvd3MgPSAyLCBtYXJnaW4gPSAwLjA1KSAlPiUgbGF5b3V0KHRpdGxlID0gJ1JRIHZzIEhESScpDQpgYGANCg0KYGBge3J9DQpzdWJwbG90KG15X3Bsb3RbMzBdLCBucm93cyA9IDEsIG1hcmdpbiA9IDAuMDUpICU+JSBsYXlvdXQodGl0bGUgPSAnUkwgdnMgSERJJykNCmBgYA0KDQouLi4gd2hhdCB3YXMgdGhhdD8/Pw0KSSBndWVzcyBJIGNhbnQganVzdCB0aHJvdyB0aGluZ3MgaW4gdGhlcmUgYW5kIGV4cGVjdCB0byBoYXZlIGEgZ29vZCBtb2RlbCwgSSBjYW4ndCBzZWUgYSBjbGVhciByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGlzIHN0dWZmLCBtb3JlIHRoYW4gYmV0dGVyIGdvdmVybmFuY2UgaW5kaWNhdG9ycyBhcmUgdXN1YWxseSBhY2NvbXBhbmllZCB3aXRoIGJldHRlciBIREkgc2NvcmVzLg0KQnV0Li4uIEkgd2FzIHNheWluZyB0aGF0IEkgd2FudGVkIHRvIGZpbmQgYSByZWxhdGlvbnNoaXAgd2l0aCBIREkgY2hhbmdlcywgbm90IHRoZSBhY3R1YWwgSERJIHNjb3JlLiBTbywgSSdsbCBjb21wdXRlIGEgSERJIGNoYW5nZSBwZXIgeWVhciBwZXIgY291bnRyeSwgKGFuZCBsb3NlIDYxIHJvd3MgaW4gdGhlIHByb2Nlc3MsIHlheS4uLikNCg0KIyBEYXRhIG1hbmlwdWxhdGlvbiAyIEVsZWN0cmljIGJvb2dhbG9vDQoNCk5vdGU6IG9yaWdpbmFsbHkgSSB3YXMgZXhjbHVkaW5nIGRhdGEgZnJvbSAyMDAxLCBiZWNhdXNlIHNvbWUgY291bnRyaWVzIGRpZG4ndCBoYXZlIGdvdmVybmFuY2UgaW5kaWNhdG9ycyBmb3IgdGhhdCB5ZWFyIHBhcnRpY3VsYXJseSwgYnV0ISwgc2luY2UgSSdsbCBsb3NlIG9uZSB5ZWFyIGJ5IGNvbXB1dGluZyB0aGUgZ3Jvd3RoIGluIGhkaSBJIGNhbiBzdGlsbCB1c2UgdGhpcyB5ZWFyIGFuZCB3b250IGxvb3NlIGRhdGEgYWwgYWxsLiBTVE9OS1MhISENCg0KYGBge3J9DQpkYXRvc19tb2RlbF8yIDwtIGRhdG9zX3BhcGVyICU+JSANCiAgICAgICAgZmlsdGVyKCFpc28yYyAlaW4lIGMoJ1NTJywgJ1pXJywgJ0JUJywgJ0VSJywgJ0dXJywgJ0tQJywgJ0xCJywgJ05HJywgJ1BTJywgJ1NPJywgJ1ZVJywgJ0ZNJywgJ0tJJywgJ1RMJywgJ0NWJywgJ1NCJyksDQogICAgICAgICAgICAgICAheWVhciAlaW4lIGMoMTk5NSwgMTk5NiwgMTk5NywgMTk5OCwgMTk5OSwgMjAwMCkpICU+JQ0KICAgICAgICBzZWxlY3QoaXNvMmMsIHllYXIsIGhkaSwgRFQuT0RBLkFMTEQuQ0QsIERULk9EQS5BTExELktELCBEVC5PREEuT0RBVC5DRCwgRFQuT0RBLk9EQVQuS0QsIERULk9EQS5PREFULlBDLlpTLA0KICAgICAgICAgICAgICAgYWxsX29mKGdzdWIoIl8iLCAiLiIsIGdvYl9pbmRpY2F0b3JzKSkNCiAgICAgICAgICAgICAgICkNCg0KdmlzX2RhdChkYXRvc19tb2RlbF8yKQ0KYGBgDQoNCmBgYHtyfQ0KZGF0b3NfbW9kZWxfMyA8LSBkYXRvc19tb2RlbF8yICU+JQ0KICBhcnJhbmdlKGlzbzJjLCB5ZWFyKSAlPiUNCiAgbXV0YXRlKGhkaV9kaWZmID0gaGRpIC0gbGFnKGhkaSkpICU+JQ0KICBmaWx0ZXIoIXllYXIgJWluJSBjKDIwMDEpKQ0KDQpkYXRvc19tb2RlbF8zICU+JSBzZWxlY3QoaXNvMmMsIHllYXIsIGhkaSwgaGRpX2RpZmYpDQoNCnZpc19kYXQoZGF0b3NfbW9kZWxfMykNCmBgYA0KYW5kIGhlcmUgd2UgZ28gYWdhaW4NCmBgYHtyfQ0KbXlfcGxvdF8zICA8LSBsaXN0KCkNCg0KZm9yIChjb2wgaW4gY29sbmFtZXMoZGF0b3NfbW9kZWxfMylbNDozM10pIHsNCiAgbXlfcGxvdF8zW1tjb2xdXSA8LSBwbG90X2x5KHggPSBkYXRvc19tb2RlbF8zW1tjb2xdXSwgeSA9IGRhdG9zX21vZGVsXzNbWzM0XV0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdtYXJrZXJzJywgbmFtZSA9IHBhc3RlKGNvbCwgInZzIEhESSBkaWZmIikpICANCn0NCg0KDQpzdWJwbG90KG15X3Bsb3RfM1sxOjVdLCBucm93cyA9IDIsIG1hcmdpbiA9IDAuMDUpICU+JSBsYXlvdXQodGl0bGUgPSAnT0RBIHZzIEhESScpDQpgYGANCg0KYGBge3J9DQpzdWJwbG90KG15X3Bsb3RfM1s2OjExXSwgbnJvd3MgPSAyLCBtYXJnaW4gPSAwLjA1KSAlPiUgbGF5b3V0KHRpdGxlID0gJ0NDIHZzIEhESSBkaWZmJykNCmBgYA0KYGBge3J9DQpzdWJwbG90KG15X3Bsb3RfM1sxMjoxN10sIG5yb3dzID0gMiwgbWFyZ2luID0gMC4wNSkgJT4lIGxheW91dCh0aXRsZSA9ICdHRSB2cyBIREkgZGlmZicpDQpgYGANCg0KYGBge3J9DQpzdWJwbG90KG15X3Bsb3RfM1sxODoyM10sIG5yb3dzID0gMiwgbWFyZ2luID0gMC4wNSkgJT4lIGxheW91dCh0aXRsZSA9ICdQViB2cyBIREkgZGlmZicpDQpgYGANCg0KYGBge3J9DQpzdWJwbG90KG15X3Bsb3RfM1syNDoyOV0sIG5yb3dzID0gMiwgbWFyZ2luID0gMC4wNSkgJT4lIGxheW91dCh0aXRsZSA9ICdSUSB2cyBIREkgZGlmZicpDQpgYGANCg0KYGBge3J9DQpzdWJwbG90KG15X3Bsb3RfM1szMF0sIG5yb3dzID0gMSwgbWFyZ2luID0gMC4wNSkgJT4lIGxheW91dCh0aXRsZSA9ICdSTCB2cyBIREkgZGlmZicpDQpgYGANCg0KVGVzdGluZyBtb2RlbCB3aGlsZSB1c2luZyBoZGlfZGlmZiBhcyBkZXBlbmRlbnQgdmFyaWFibGUgKGl0IHdlbnQgYmV0dGVyIHRoYW4gZXhwZWN0ZWQpDQpgYGB7cn0NCm1vZGVsXzMgPC0gbG0oaGRpX2RpZmYgfiBEVC5PREEuQUxMRC5DRCArIENDLkVTVCArIEdFLkVTVCArIFBWLkVTVCArIFJRLkVTVCArIFJMLkVTVCwgZGF0YT1kYXRvc19tb2RlbF8zKQ0Kc3VtbWFyeShtb2RlbF8zKQ0KYGBgDQpJIGxpa2VkIHRoZSByZWxhdGlvbnNoaXAgdmlzaWJsZSBpbiB0aGUgUEVSLlJOSyBnb3YgaW5kaWNhdG9ycywgbGV0J3MgdHJ5IGEgbW9kZWwgd2l0aCB0aG9zZSB2YXJpYWJsZXMgKGl0IHdlbnQgd29yc2UgdGhhbiBleHBlY3RlZCkNCmBgYHtyfQ0KbW9kZWxfNCA8LSBsbShoZGlfZGlmZiB+IERULk9EQS5BTExELkNEICsgQ0MuUEVSLlJOSyArIEdFLlBFUi5STksgKyBQVi5QRVIuUk5LICsgUlEuUEVSLlJOSyArIFJMLkVTVCwgZGF0YT1kYXRvc19tb2RlbF8zKQ0Kc3VtbWFyeShtb2RlbF80KQ0KYGBg